# !/usr/bin/python
# -*- coding: UTF-8 -*-

import os
import sys
import re
from pylab import *
import numpy as np
import matplotlib
import matplotlib.colors as colors
import matplotlib.pyplot as plt
from random import randrange
from matplotlib.ticker import MultipleLocator, FormatStrFormatter

#处理文件数据,文件路径,每秒发送包数，更多信息在文件(True)或目录名
def plotfiledata(filepath,avgpacket = 1,info = True):
    # 读入数据文件
    fs = open(filepath, "rb")
    lines = fs.readlines()
    fs.close()
    
    power = '19'
    dist = '00'
    mac = '00:00:00:00:00:00'
    start_time = '2017-02-20 00:00:00'
    stop_time = '2017-02-20 00:00:00'
    rssiavg = 0
    occl = 'no'
    plk = 0
    nor = 0
    apc = 0
    
    for i in range(0,len(lines)):
        if lines[i][0] == '#':
            sstr = lines[i].split()    
            if sstr[1] == 'mac':
                mac = sstr[2]
            elif sstr[1] == 'start_time':
                start_time = '_'.join(sstr[2:])
            elif sstr[1] == 'stop_time':
                stop_time = '_'.join(sstr[2:])
        if 'stop_time' not in lines[i] and len(lines) > 6:
            stop_time = lines[-2].split()[1] + '_' + lines[-2].split()[2]
    if info:#更多信息在文件内部
        for i in range(0,len(lines)):
            if lines[i][0] == '#':
                sstr = lines[i].split()    
                if sstr[1] == 'power':
                    power = sstr[2]
                elif sstr[1] == 'dist':
                    dist = sstr[2]
                elif sstr[1] == 'occl':
                    occl = sstr[2]
    else:#更多信息不在文件内部
        #获取上级目录名
        s = os.path.abspath(filepath).split('/')[-2] 
        power = s.split('_')[0]
        dist = s.split('_')[1]
        occl = s.split('_')[2]
        
    #print mac,start_time,stop_time,power,dist,occl
    
    sstr = []
    time = []
    rssi = []
    for i in range(0,len(lines)):
        if 'time' in lines[i] and 'rssi' in lines[i]:
            sstr.append(lines[i][lines[i].index('time') + 16 : lines[i].index('time') + 31].split(':'))
            rssi.append(int(lines[i][lines[i].index('rssi') + 5 : lines[i].index('rssi') + 9]))
    for i in range(0,len(sstr)):
        time.append(int(sstr[i][0]) * 3600 + int(sstr[i][1]) * 60 + float(sstr[i][2]))
    #print time,rssi,len(time),len(rssi),len(time)/float(max(time)-min(time))
    timeloss = []
    rssiloss = []
    if len(time) == len(rssi):
        for i in range(0,len(time) - 1):
            ti = (time[i + 1] - time[i])
            if (ti > ((1.0/avgpacket) * 1.5)):
                for j in range(0,int(ti/(1.0/avgpacket))):
                    timeloss.append(time[i] + j * (1.0/avgpacket) + (1.0/avgpacket))
                    rssiloss.append(-110)
    else:
        exit()
    if len(time) > 0:
        nor = int((max(time)-min(time)) * avgpacket)
    else:
        return
        #s1 = start_time.split('_')[-1].split(':')
        #s2 = stop_time.split('_')[-1].split(':')
        #nor = int((int(s2[0]) * 3600 + int(s2[1]) * 60 + float(s2[2])) - (int(s1[0]) * 3600 + int(s1[1]) * 60 + float(s1[2])))
    apc = len(time)
    plk = (1 - apc/float(nor)) * 100
    if plk < 0:
        plk = 0
    for i in rssi:
        rssiavg += i
    rssiavg = int(rssiavg/float(len(rssi) + 0.5))
    fo = open(sys.argv[2] + '/' + "allreport/allreport.txt", "ab")
    fo.write("$ power %s dist %s mac %s nor %s apc %s plk %s rssi %s occl %s\r\n" % (power,dist,mac,nor,apc,plk,rssiavg,occl))
    fo.close()
   
    fg = plt.figure(figsize=(16,20))
    ax1 = fg.add_subplot(111)
    ax1.set_title('Bluetooth packet loss test') 
    # 设置X轴范围
    xlim(min(time) - 10,max(time) + 10)
    # 设置y轴范围
    ylim(-120,0)

    plt.xlabel('Time (S)')
    plt.ylabel('Rssi (dB)')
    
    plt.text(min(time) + 5, -2 ,'Power: %sdB   Dist: %sm' % (power,dist),color='red')
    plt.text(min(time) + 5, -4 ,'MAC: %s' % (mac),color='green')
    plt.text(min(time) + 5, -6 ,'NOR: %d, APC: %d, PKL: %f %%' % (nor,apc,plk),color='blue')
    plt.text(min(time) + 5, -8 ,'RSSI: %d dB, OCCL: %s' % (rssiavg,occl),color='blue')
    plt.text(min(time) + 5, -10,'start time: %s' % (start_time),color='blue')
    plt.text(min(time) + 5, -12,'stop time: %s' % (stop_time),color='blue')
    
    #plt.text(min(time) + 5, rssiavg + 10,'get',color='green',fontsize = 32)
    #plt.text(min(time) + 5, -105,'loss',color='red',fontsize = 32) 
    
    plt.grid(True)

    ax1.scatter(time,rssi,c = 'g',marker = 'x',label = 'Got')
    ax1.scatter(timeloss,rssiloss,c = 'r',marker = 'x',label = 'Loss') 
    ax1.legend(loc='upper right')
    
    plt.savefig(os.path.splitext(filepath)[0] + '_'+ power + '_' + dist + '_' + occl + ".jpg")
    #plt.xticks(range(int(min(time)),int(max(time))+1,100))
    #plt.show()
    plt.close()
    
    print 'Power: %sdB   Dist: %sm' % (power,dist)
    print 'MAC: %s' % (mac)
    print 'NOR: %d, APC: %d, PKL: %f %%' % (nor,apc,plk)
    print 'RSSI: %d dB, OCCL: %s' % (rssiavg,occl)
    print 'start time: %s' % (start_time)
    print 'stop time: %s' % (stop_time)
    print ''
    
    #print time
    
    return;
    
# 解析原始数据，输入参数 -> 数据文件路径
def deal(datapath):
    # 读入数据文件
    fs = open(datapath, "rb")
    fo = open(os.path.splitext(datapath)[0] + "_data.txt", "wb")
    lines = fs.readlines()
    fs.close()

    power = '10'
    dist = '10'
    mac = '00:00:00:00:00:00'
    start_time = 'Tue_Feb_14_14:43:03_2017'
    stop_time = 'Tue_Feb_14_14:43:03_2017'
    rssi = 0
    counts = 0
    occl = 'no'
    
    for i in range(0,len(lines)):
        linestart = lines[i].find('data') + 11
        if lines[i][0] != '#':
            d = (   int(lines[i][linestart + 0:linestart + 2],16) + 
                    256 * int(lines[i][linestart + 3:linestart + 5],16)  + 
                    256 * 256 * int(lines[i][linestart + 6:linestart + 8],16)  + 
                    256 * 256 * 256 * int(lines[i][linestart + 9:linestart + 11],16)
                )
            if 'rssi' in lines[i]:
                ri = int(lines[i].split()[lines[i].split().index('rssi') + 1],16)
                fo.write("%d %d\r\n" % (d,ri))
                rssi += ri
                counts += 1
            else:
                fo.write("%d\r\n" % (d))
        else:
            sstr = lines[i].split()    
            if sstr[1] == 'power':
                power = sstr[2]
            elif sstr[1] == 'dist':
                dist = sstr[2]
            elif sstr[1] == 'occl':
                occl = sstr[2]
            elif sstr[1] == 'mac':
                mac = sstr[2]
                print "物理地址：%s" % (mac)
            elif sstr[1] == 'start_time':
                start_time = '_'.join(sstr[2:])
            elif sstr[1] == 'stop_time':
                stop_time = '_'.join(sstr[2:])
    fo.close()
    if counts == 0:
       rssi = -120
    else:
       rssi = rssi/(counts*1.0)  
    return mac,power,dist,start_time,stop_time,rssi,occl;

# 实线图 根据解析原始数据后的数据解析数据，输入参数 -> 数据文件路径
def analyplot(datapath,mac):
    # 读入数据文件
    fo = open(datapath, "rb")
    lines = fo.readlines()
    data = [int(i) for i in lines]
    datalen = len(data)
    pkgnum = (data[datalen - 1] + 1) - data[0]
    print "应收包数：%d" % pkgnum
    print "实收包数：",datalen
    print "丢包率：",((1 - datalen/(pkgnum * 1.0)) * 100 ) ,"%"
    fo.close()

    start = data[0]
    y = range(0,pkgnum,1)
    for i in range(0,len(y)):
        y[i] = 1
        
    j = 0
    for i in range(start,start + pkgnum):
        if i == data[j]:
            y[i - start] = 1
            j += 1
        else :
            y[i - start] = 0                            
    # print y

    x = np.arange(start,start + pkgnum,1)
    # 设置X轴范围
    xlim(start,start + pkgnum)
    # 设置y轴范围
    ylim(-0.5,1.5)

    plt.xlabel('pkg num')
    plt.ylabel('yes or no')

    # 实线图
    plt.plot(x, y, 'b-')
    plt.show()
    
    return;
    
# 散点图 根据解析原始数据后的数据解析数据，输入参数 -> 数据文件路径
def analyscatter(datapath,p):
    # 读入数据文件
    fo = open(datapath, "rb")
    lines = fo.readlines()
    if len(lines) == 0:
        return;
    data = [int(i.split()[0]) for i in lines]
    rssi = [int(i.split()[1]) for i in lines]
    datalen = len(data)
    pkgnum = (data[datalen - 1] + 1) - data[0]
    loss = ((1 - datalen/(pkgnum * 1.0)) * 100 )
    print "应收包数：%d , %d~%d" % (pkgnum,data[0],((data[datalen - 1] + 1)))
    print "实收包数：",datalen
    print "丢包率：", loss,"%"
    fo.close()

    start = data[0]
    y = range(0,pkgnum,1)
    for i in range(0,len(y)):
        y[i] = 1
        
    j = 0
    for i in range(start,start + pkgnum):
        if i == data[j]:
            y[i - start] = 1
            j += 1
        else :
            y[i - start] = 0
            rssi.insert(i-start,(rssi[i-start-1]) if ((i-start-1) >= 0) else 0)                            
    #print y,rssi
    #print len(y),len(rssi)
    fo = open(sys.argv[2] + '/' + "allreport/allreport.txt", "ab")
    fo.write("$ power %s dist %s mac %s nor %s apc %s plk %s rssi %d occl %s\r\n" % (p[1],p[2],p[0][0:17],pkgnum,datalen,loss,p[5],p[6]))
    fo.close()
    
    x = np.arange(start,start + pkgnum,1)
    
    fg = plt.figure(figsize=(16,20))
    ax1 = fg.add_subplot(211)
    ax1.set_title('Bluetooth packet loss test') 
    # 设置X轴范围
    xlim(start - 10,start + pkgnum + 10)
    # 设置y轴范围
    ylim(-0.5,1.5)

    plt.xlabel('Packet number')
    plt.ylabel('Receiving situation')

    plt.text(start-8, 1.45,'Power: %sdB   Dist: %sm' % (p[1],p[2]),color='red')
    plt.text(start-8, 1.4 ,'MAC: %s' % p[0][0:17],color='green')
    plt.text(start-8, 1.35,'NOR: %d , %d~%d, APC: %d, PKL: %d %%' % (pkgnum,data[0],((data[datalen - 1] + 1)),datalen,loss),color='blue')
    plt.text(start-8, 1.3 ,'RSSI: %d dB, OCCL: %s' % (p[5],p[6]),color='blue')
    plt.text(start-8, 1.25,'start time: %s' % (p[3]),color='blue')
    plt.text(start-8, 1.2 ,'stop time: %s' % (p[4]),color='blue')
    
    plt.text(start-8, 1.05,'get',color='red',fontsize = 32)
    plt.text(start-8, 0.05,'loss',color='red',fontsize = 32)  
            
    ax1.scatter(x,y,c = 'r',marker = 'x') 
    
    ax2=fg.add_subplot(212)
    ax2.set_title('Bluetooth RSSI') 
    xlim(start - 10,start + pkgnum + 10)
    ylim(-120,0)
    plt.xlabel('Packet number')
    plt.ylabel('RSSI (dB)')
    plt.plot(x, rssi, 'b-')
    
    plt.savefig(os.path.splitext(datapath)[0][:-5] + '_'+ p[1] + '_' + p[2] + '_' + p[6] + ".jpg")
    #plt.show()
    
    return;

#list2 按list1升序排列    
def sort2list(list1,list2):
    a = list1
    b = list2
    data=[(a, b) for a,b in zip(a,b)] #先转化成元组
    data.sort()
    list1 = [a for a,b in data] 
    list2 = [b for a,b in data]
    return list1,list2;

#data 字典列表 x轴键值 y轴键值 x轴范围 y轴范围 遮挡状况 发射功率 保存路径
def plotplot(data,strx,stry,xrang,yrang,occl,power,savepath):
    if stry == 'plk': 
        ylable = 'Packet loss (%)'
        title = 'Packet loss contrast'
    elif stry == 'rssi': 
        ylable = 'RSSI (dB)'
        title = 'Signal strength contrast'
    else:
        ylable = stry
#    xmajorLocator = MultipleLocator(10) #将x主刻度标签设置为10的倍数         
    for k in range(0,len(occl)):
        # 画图
        ax = plt.figure(num=1, figsize=(16, 12)).add_subplot(111)
        ax.set_title(title + ' ' + occl[k] + ' occl')
        # 设置X轴范围
        plt.xlim(xrang[0],xrang[-1])
        # 设置y轴范围
        plt.ylim(yrang[0],yrang[-1])
        plt.xlabel('Distance(m)')
        plt.ylabel(ylable)
        at = False
        for i in range(0,len(data)):
            if (data[i]['occl'] == occl[k]):
                cl = "#%06X" % (randrange(0XA00000, 0XFF0000,1000))     
                pl = plt.plot(data[i][strx],data[i][stry],'-',color = cl,label = (data[i]['mac'] + ' ' + str(data[i]['power']) + 'dB'))
                at = True      
        if at:
            ax.legend(loc='upper right') 
            plt.savefig(savepath + 'Contrast_' + stry + '_' + str(occl[k]) + '.jpg')
        plt.close()
        #plt.show()
    return;

def Contrastplot(filepath):
    point = {'power':[],'dist':[],'mac':[],'nor':[],'apc':[],'plk':[],'rssi':[],'occl':[]}
    data = [] 
    mac = [] 
    power = [] 
    occl = []
#    dist = []
    fs = open(filepath,'rb')
    lines = fs.readlines()
    fs.close()
    for i in range(0,len(lines)):
        # 按空格 拆分字符串
        sstr = lines[i].split()
        if '$' == sstr[0]:
            point['power'].append(int(sstr[sstr.index("power") + 1]))
            point['dist'].append(int(sstr[sstr.index("dist") + 1]))
            point['mac'].append(sstr[sstr.index("mac") + 1])
            point['nor'].append(int(sstr[sstr.index("nor") + 1]))
            point['apc'].append(int(sstr[sstr.index("apc") + 1]))
            point['plk'].append(float(sstr[sstr.index("plk") + 1]))
            point['rssi'].append(int(sstr[sstr.index("rssi") + 1]))
            point['occl'].append(sstr[sstr.index("occl") + 1])
            
            if (int(sstr[sstr.index("power") + 1])) not in power:
                power.append(int(sstr[sstr.index("power") + 1]))
#            if (int(sstr[sstr.index("dist") + 1])) not in dist:
#                dist.append(int(sstr[sstr.index("dist") + 1])) 
            if (sstr[sstr.index("mac") + 1]) not in mac:
                mac.append(sstr[sstr.index("mac") + 1])
            if (sstr[sstr.index("occl") + 1]) not in occl:
                occl.append(sstr[sstr.index("occl") + 1]) 
                #print occl 
        # 排序
    power.sort()
#    dist.sort() 
#    print occl            
    for k in range(0,len(occl)):#遮挡情况
        for j in range(0,len(power)):#功率
            for i in range(0,len(mac)):#物理地址
                data.append({'occl':occl[k],'mac':mac[i],'power':power[j],'dist':[],'plk':[],'rssi':[]})
                #print data
    for i in range(0,len(mac)*len(power)*len(occl)):
        for j in range(0,len(point['plk'])):
            if point['occl'][j] == data[i]['occl'] and point['power'][j] == data[i]['power'] and point['mac'][j] == data[i]['mac']:
                data[i]['dist'].append(point['dist'][j])
                data[i]['plk'].append(point['plk'][j])
                data[i]['rssi'].append(point['rssi'][j])    
    #print data
    data2 = []
    for i in range(0,len(data)):
        p = sort2list(data[i]['dist'],data[i]['plk'])
        data[i]['dist'] = p[0]
        data[i]['plk'] = p[1]
        p = sort2list(data[i]['dist'],data[i]['rssi'])
        data[i]['dist'] = p[0]
        data[i]['rssi'] = p[1] 
        
        if (len(data[i]['plk']) != 0) and ((len(data[i]['rssi']) != 0)):# and (data[i]['power'] in power) and (data[i]['occl'] == power[j]):
            data2.append(data[i])
    #print data2
    data = data2
    #print occl
    plotplot(data,'dist','plk',(0,150),(-10,110),occl,power,os.path.split(sys.argv[2])[0] + '/')
    plotplot(data,'dist','rssi',(0,150),(-120,0),occl,power,os.path.split(sys.argv[2])[0] + '/')
        
    return;

class searchfile():
    def __init__(self):
        self.namelist = []
        
    def search(self,path, con):
        for filename in os.listdir(path):
            fp = os.path.join(path, filename)
            if os.path.isfile(fp) and re.match(con,os.path.basename(fp)): 
                self.namelist.append(fp)
            elif os.path.isdir(fp):
                self.search(fp, con)
        return self.namelist;        

def printusage():
    print "Usage:"
    print "     python blepkg.py [-h help] [-f/-d file/dir] [file name / Matching condition] [-o/-p] [ /avgpacket] [info]"
    print "     python blepkg.py -d ./ '^00_0b.*?[^data].txt$' "
    print "     python blepkg.py -d ./19_00_no/ '.*?.txt$' -o 1 False "
    return;

if __name__ == '__main__':
    #print sys.argv
    if (len(sys.argv) < 3) or ('-h' in sys.argv):
        printusage()
        exit()
    if '-c' in sys.argv:
        Contrastplot(sys.argv[2])  
    else:
        if not os.path.exists(sys.argv[2] + '/' + 'allreport/'):
            os.makedirs(sys.argv[2] + '/' + 'allreport/')
        if os.path.exists(sys.argv[2] + '/' + "allreport/allreport.txt"):
           os.remove(sys.argv[2] + '/' + "allreport/allreport.txt")
        if '-f' in sys.argv:
            filelist = []
            filelist.append(sys.argv[2])
        elif '-d' in sys.argv:    
            filelist = searchfile().search(sys.argv[2],sys.argv[3])
        for filename in filelist:
            if '-p' in sys.argv:
                if os.path.exists(os.path.splitext(filename)[0] + "_data.txt"):
                    os.remove(os.path.splitext(filename)[0] + "_data.txt")
                analyscatter(os.path.splitext(filename)[0] + "_data.txt",deal(filename))
            elif '-o' in sys.argv:
                if '-f' in sys.argv:
                    plotfiledata(filename,int(sys.argv[4]),(False if sys.argv[5] == 'False' else True))
                else:
                    plotfiledata(filename,int(sys.argv[5]),(False if sys.argv[6] == 'False' else True))
            
    print "Over"        
    


